//
//  Functions.swift
//  swiftProject
//
//  Created by yangjian on 2021/11/23.
//

import Foundation
import UIKit
import SwiftUI
import Photos
import MobileCoreServices


func application_statusBarHeight() -> CGFloat {
    if #available(iOS 13.0, *) {
        return application_keyWindow()?.windowScene?.statusBarManager?.statusBarFrame.size.height ?? 0
    } else {
        return UIApplication.shared.statusBarFrame.size.height
    }
}

func application_keyWindow() -> UIWindow? {
    if #available(iOS 13.0, *) {
        let keyWindow =
        UIApplication.shared.connectedScenes
            .filter{
                $0.activationState == .foregroundActive
                || $0.activationState == .background
                || $0.activationState == .unattached
            }.map{
                $0 as? UIWindowScene
            }.compactMap({$0}).first?.windows.filter {
                $0.isKeyWindow
            }.first;
//        if let keyWindow{
//            return keyWindow
//        }
        return keyWindow
    } else {
        return UIApplication.shared.keyWindow!
    }
}

func application_keyWindowSetRootViewController(rootViewController:UIViewController){
    let keyWindow = application_keyWindow()
    keyWindow?.rootViewController = rootViewController
    keyWindow?.makeKeyAndVisible()
}

func screen_width() -> CGFloat {
    return UIScreen.main.bounds.size.width
}

func screen_height() -> CGFloat {
    return UIScreen.main.bounds.size.height
}

func safearea_top() ->CGFloat {
    application_keyWindow()?.safeAreaInsets.top ?? 0
}

func safearea_bottom() ->CGFloat {
    application_keyWindow()?.safeAreaInsets.bottom ?? 0
}
func safearea_left() ->CGFloat {
    application_keyWindow()?.safeAreaInsets.left ?? 0
}

func safearea_right() ->CGFloat {
    application_keyWindow()?.safeAreaInsets.right ?? 0
}

func navigation_top(navigationController:UINavigationController?) -> CGFloat {
    if navigationController != nil {
        return application_statusBarHeight() + navigationController!.navigationBar.frame.size.height
    }else{
        return application_statusBarHeight()
    }
}

func color_hex_RGB(rgb : UInt32) -> UIColor {
    let red = CGFloat(Int(rgb & 0xff0000)  >> 16)   / 255.0
    let green = CGFloat(Int(rgb & 0xff00)  >> 8)    / 255.0
    let blue = CGFloat(Int(rgb & 0xff))             / 255.0
    return UIColor.init(red: red, green: green, blue: blue, alpha: 1)
}

func color_hex_RGBA(rgb : UInt32) -> UIColor {
    let red     = CGFloat(Int(rgb & 0xff000000)  >> 24) / 255.0
    let green   = CGFloat(Int(rgb & 0xff0000)  >> 16)   / 255.0
    let blue    = CGFloat(Int(rgb & 0xff00)  >> 8)      / 255.0
    let alpha   = CGFloat(Int(rgb & 0xff))              / 255.0
    return UIColor.init(red: red, green: green, blue: blue, alpha: alpha)
}


//string
func attributedString(string : String , font : UIFont , color:UIColor) -> NSAttributedString {
    return NSAttributedString.init(
            string: string,
            attributes: [
                NSAttributedString.Key.foregroundColor:color,
                NSAttributedString.Key.font:font
        ]
    )
}

//文字计算高度
func fitHeight_attributedString(attributedString : NSAttributedString , maxWidth : CGFloat) -> CGFloat {
    return CGFloat(ceilf(
        Float(attributedString.boundingRect(
            with:
                CGSize(
                    width:
                        maxWidth,
                    height: CGFloat.greatestFiniteMagnitude),
            options: [.usesLineFragmentOrigin,.usesFontLeading],
            context: nil).size.height)))
}

//string.boundingRect(with: <#T##CGSize#>, options: <#T##NSStringDrawingOptions#>, context: <#T##NSStringDrawingContext?#>)
//文字计算高度
func fitHeight_string(string : String ,font : UIFont, maxWidth : CGFloat) -> CGFloat {
    return CGFloat(ceilf(Float(string.boundingRect(with:
                                                CGSize(
                                                    width:maxWidth,
                                                    height: CGFloat.greatestFiniteMagnitude),
                                                   options: [.usesLineFragmentOrigin,.usesFontLeading],
                                               attributes: [.font : font],
                                                   context: nil).size.height)))
}




//文件 - 创建路径(文件夹)
func directory_createIfNotExists(directoryPath : String) -> Bool {
    var isDirectory : ObjCBool = false
    var isExist = false
    isExist = FileManager.default.fileExists(atPath: directoryPath, isDirectory: &isDirectory)
    if isExist && isDirectory.boolValue {
        return true
    }
    
    do{
        try FileManager.default.createDirectory(atPath: directoryPath, withIntermediateDirectories: true, attributes: nil)
        return true
    }catch{
        print(error)
    }
    return false
}

//文件 - 是否存在
func file_fileExists(filePath : String) -> Bool {
    var isDirectory = ObjCBool.init(false)
    if FileManager.default.fileExists(atPath: filePath, isDirectory: &isDirectory) {
        if isDirectory.boolValue {
            return false
        }else {
            return true
        }
    }else{
        return false
    }
}


//文件 - 语音专用
func file_fetchVoickWAVFilePath(filePath : String) -> String {
    
    var voicePath = ""
    if filePath.hasSuffix(".wav") {
        voicePath = filePath
    }else if filePath.hasSuffix(".mp3") {
        voicePath = filePath
    }else if filePath.hasSuffix(".amr") {
        voicePath = filePath.replacingOccurrences(of: ".amr", with: ".wav")
    }else{
        voicePath = filePath + ".wav"
    }
    
    if !(JJVoiceRecordHelper.shared().convertAMRtoWAV_amrPath(filePath, wavPath: voicePath)) {
        voicePath = ""
    }
    return voicePath
}



func directory_appSupport() -> String{
    return "\(NSHomeDirectory())/Library/Application Support"
}
func directory_cache() -> String{
    return "\(NSHomeDirectory())/Library/Caches"
}

//路径 - 临时文件的路径
func directory_cacheFiles(appkey : String = "") -> String{
    var directoryPath = ""
    if appkey.count > 0 {
        directoryPath = "\(directory_cache())/\(appkey)/files"
    }else{
        directoryPath = "\(directory_cache())/no_appkey/files"
    }
    if !directory_createIfNotExists(directoryPath: directoryPath) {
        directoryPath = ""
    }
    return directoryPath
}



//路径 - 创建userinfo的路径 必须要有appkey
func directory_userInfo(appkey : String = "") -> String {
    var directoryPath = ""
    if appkey.count > 0 {
        directoryPath = "\(directory_appSupport())/\(appkey)/userinfodbs"
    }else{
        print("directory_userInfo 没有appkey,无法初始化userinfo的数据库")
        return ""
    }
    if !directory_createIfNotExists(directoryPath: directoryPath) {
        directoryPath = ""
    }
    return directoryPath
}

//路径 - 音文件voice的路径
func directory_voice(appkey : String = "") -> String {
    var directoryPath = ""
    if appkey.count > 0 {
        directoryPath = "\(directory_appSupport())/\(appkey)/voice"
    }else{
        directoryPath = "\(directory_appSupport())/no_appkey/voice"
    }
    if !directory_createIfNotExists(directoryPath: directoryPath) {
        directoryPath = ""
    }
    return directoryPath
}

//其他文件 file 路径
func directory_files(appkey : String = "") -> String {
    var directoryPath = ""
    if appkey.count > 0 {
        directoryPath = "\(directory_appSupport())/\(appkey)/files"
    }else{
        directoryPath = "\(directory_appSupport())/no_appkey/files"
    }
    if !directory_createIfNotExists(directoryPath: directoryPath) {
        directoryPath = ""
    }
    return directoryPath
}

//生成随机字符串(相对随机,不算标准)
var _randomStringTimestamp  = Int(Date().timeIntervalSince1970 * 1000)
func generate_randomString(prefix : String?,suffix : String?) -> String{
    var timestamp = Int(Date().timeIntervalSince1970 * 1000)
    if timestamp <= _randomStringTimestamp {
        timestamp = _randomStringTimestamp + 1
    }
    _randomStringTimestamp = timestamp
    var p = ""
    var s = ""
    
    if let prefix {
        p = prefix
    }
    if let suffix {
        s = suffix
    }
    return "\(p)\(_randomStringTimestamp)\(s)"
}

func nsranges(string:String , subString: String) -> [NSRange] {
    return ranges(string:string, subString:subString).map { (range) -> NSRange in
        nsrange(string: string, fromRange: range)
    }
}

func nsrange(string : String,fromRange range : Range<String.Index>) -> NSRange {
    return NSRange(range, in: string)
}

func ranges(string:String , subString: String) -> [Range<String.Index>] {
    var rangeArray = [Range<String.Index>]()
    var searchedRange: Range<String.Index>
    guard let sr = string.range(of: string) else {
        return rangeArray
    }
    searchedRange = sr
    var resultRange = string.range(of: subString, options: .regularExpression, range: searchedRange, locale: nil)
    while let range = resultRange {
        rangeArray.append(range)
        searchedRange = Range(uncheckedBounds: (range.upperBound, searchedRange.upperBound))
        resultRange = string.range(of: subString, options: .regularExpression, range: searchedRange, locale: nil)
    }
    return rangeArray
}


//————————————————
//版权声明：本文为CSDN博主「明似水」的原创文章，遵循CC 4.0 BY-SA版权协议，转载请附上原文出处链接及本声明。
//原文链接：https://blog.csdn.net/smileKH/article/details/130623677
//关于视频size和视频第一帧

//视频的size ,这里设定的是 30 * 30
func video_size(by videoURL: URL?) -> CGSize {
    var size: CGSize = .zero
    size = CGSizeMake(30, 30)
    guard let videoURL = videoURL else {
        return size
    }
//    var aset = PHAsset()
    let asset = AVAsset(url: videoURL)
    let tracks = asset.tracks(withMediaType: AVMediaType.video)
    guard let track = tracks.first else {
        return size
    }
    let t = track.preferredTransform
    size = CGSize(width: track.naturalSize.height, height: track.naturalSize.width)

    if t.a == 0 && t.b == 1.0 && t.c == -1.0 && t.d == 0 {
        size = CGSize(width: track.naturalSize.height, height: track.naturalSize.width)
    } else if t.a == 0 && t.b == -1.0 && t.c == 1.0 && t.d == 0 {
        // PortraitUpsideDown
        size = CGSize(width: track.naturalSize.height, height: track.naturalSize.width)
    } else if t.a == 1.0 && t.b == 0 && t.c == 0 && t.d == 1.0 {
        // LandscapeRight
        size = CGSize(width: track.naturalSize.width, height: track.naturalSize.height)
    }else if t.a == -1.0 && t.b == 0 && t.c == 0 && t.d == -1.0 {
        // LandscapeLeft
        size = CGSize(width: track.naturalSize.width, height: track.naturalSize.height)
    }
    return size
}

//获取视频第一帧
func video_splitFPStoImage(videoURL: URL, fps: Float, splitCompleteClosure: @escaping (Bool, [UIImage]) -> Void) {
    var splitImages = [UIImage]()
    let optDict = NSDictionary(object: NSNumber(value: false), forKey: AVURLAssetPreferPreciseDurationAndTimingKey as NSCopying)
    let urlAsset = AVURLAsset(url: videoURL, options: optDict as? [String: Any])

    let cmTime = urlAsset.duration
    let durationSeconds: Float64 = CMTimeGetSeconds(cmTime) //视频总秒数

    var times = [NSValue]()
    let totalFrames: Float64 = durationSeconds * Float64(fps) //获取视频的总帧数
    var timeFrame: CMTime

    for i in 0...Int(totalFrames) {
        timeFrame = CMTimeMake(value: Int64(i), timescale: Int32(fps)) //第i帧， 帧率
        let timeValue = NSValue(time: timeFrame)

        times.append(timeValue)
    }

    //杨剑修改,框内是杨剑添加部分,这里只获取第一帧,所以将数据移除到只剩第一个,如果不需要,直接将onlyFirst赋值false即可
    //============================================
    let onlyFirst = true                        //
    if onlyFirst {                              //
        if let first = times.first {            //
            times = [first]                     //
        }                                       //
    }                                           //
    //============================================
    
    let imgGenerator = AVAssetImageGenerator(asset: urlAsset)
    imgGenerator.requestedTimeToleranceBefore = CMTime.zero //防止时间出现偏差
    imgGenerator.requestedTimeToleranceAfter = CMTime.zero
    imgGenerator.appliesPreferredTrackTransform = true //不知道是什么属性，不写true视频帧图方向不对

    let timesCount = times.count
    
    //获取每一帧的图片
    imgGenerator.generateCGImagesAsynchronously(forTimes: times) { (requestedTime, image, actualTime, result, error) in
        //times有多少次body就循环多少次。。。
        var isSuccess = false
        switch (result) {
        case AVAssetImageGenerator.Result.cancelled:
            print("cancelled------")
        case AVAssetImageGenerator.Result.failed:
            print("failed++++++")
        case AVAssetImageGenerator.Result.succeeded:
            let framImg = UIImage(cgImage: image!)
            splitImages.append(framImg)
            if (Int(requestedTime.value) == (timesCount - 1)) { //最后一帧时 回调赋值
                isSuccess = true
                splitCompleteClosure(isSuccess, splitImages)
                print("completed")
            }
        @unknown default: break
        }
    }
}

//获取视频时长
func video_duration(videoURL : URL) -> Int{
    let asset = AVURLAsset(url: videoURL) as AVURLAsset
    let totalSeconds = Int(CMTimeGetSeconds(asset.duration))
    let minutes = totalSeconds / 60
    let seconds = totalSeconds % 60
    let mediaTime = String(format:"%02i:%02i",minutes, seconds)
    print("打印视频的时长=======",totalSeconds)
    return totalSeconds
}

//根据asset获取文件扩展名
//import Photos
//import MobileCoreServices
func phassetResource_fetchFileExtension(resource : PHAssetResource) -> String {
    /*
     resource获取方式
     guard let resource = PHAssetResource.assetResources(for: asset).first else {
         print("没有PHAssetResource,也可能是权限问题")
         continue
     }
     */
    print(resource.originalFilename)
    print(resource.originalFilename.components(separatedBy: ".").last ?? "")
    if let fileExtension = UTTypeCopyPreferredTagWithClass(resource.uniformTypeIdentifier as CFString, kUTTagClassFilenameExtension)?.takeRetainedValue() {
        print("File type is: \(fileExtension)")
        return fileExtension as String
    }
    return ""
}
